#ifdef USE_EXT_GPIO

#ifndef _ESP_EXT_H_
#define _ESP_EXT_H_

#include <linux/interrupt.h>
#include <linux/module.h>
#include "esp_sip.h"

#define MAX_PENDING_INTR_LIST 16

#ifdef EXT_GPIO_OPS
typedef struct esp_ext_gpio_ops {
	int (*gpio_request) (int gpio_no);	/* gpio_request gpio_no from 0x0 to 0xf */
	int (*gpio_release) (int gpio_no);	/* gpio_release */
	int (*gpio_set_mode) (int gpio_no, int mode, void *data);	/* gpio_set_mode, data is irq_func of irq_mode , default level of output_mode */
	int (*gpio_get_mode) (int gpio_no);	/* gpio_get_mode, current mode */
	int (*gpio_set_state) (int gpio_no, int state);	/* only output state, high level or low level */
	int (*gpio_get_state) (int gpio_no);	/* current state */
	int (*irq_ack) (int gpio_no);	/* ack interrupt */
} esp_ext_gpio_ops_t;
#endif

typedef enum EXT_GPIO_NO {
	EXT_GPIO_GPIO0 = 0,
	EXT_GPIO_U0TXD,
	EXT_GPIO_GPIO2,
	EXT_GPIO_U0RXD,
	EXT_GPIO_GPIO4,
	EXT_GPIO_GPIO5,
	EXT_GPIO_SD_CLK,
	EXT_GPIO_SD_DATA0,
	EXT_GPIO_SD_DATA1,
	EXT_GPIO_SD_DATA2,
	EXT_GPIO_SD_DATA3,
	EXT_GPIO_SD_CMD,
	EXT_GPIO_MTDI,
	EXT_GPIO_MTCK,
	EXT_GPIO_MTMS,
	EXT_GPIO_MTDO,
	EXT_GPIO_MAX_NUM
} EXT_GPIO_NO_T;

typedef enum EXT_GPIO_MODE {	//dir           def     pullup  mode    wake
	EXT_GPIO_MODE_OOB = 0,	//output        1       0       n/a     n/a
	EXT_GPIO_MODE_OUTPUT,	//output        /       0       n/a     n/a
	EXT_GPIO_MODE_DISABLE,	//input         n/a     0       DIS     n/a
	EXT_GPIO_MODE_INTR_POSEDGE,	//input         n/a     0       POS     1
	EXT_GPIO_MODE_INTR_NEGEDGE,	//input         n/a     1       NEG     1
	EXT_GPIO_MODE_INPUT,	//input         n/a     0       ANY     1
	EXT_GPIO_MODE_INTR_LOLEVEL,	//input         n/a     1       LOW     1
	EXT_GPIO_MODE_INTR_HILEVEL,	//input         n/a     0       HIGH    1
	EXT_GPIO_MODE_MAX,
} EXT_GPIO_MODE_T;

typedef enum EXT_GPIO_STATE {
	EXT_GPIO_STATE_LOW,
	EXT_GPIO_STATE_HIGH,
	EXT_GPIO_STATE_IDLE
} EXT_GPIO_STATE_T;

typedef irqreturn_t(*ext_irq_handler_t) (void);

struct ext_gpio_info {
	int gpio_no;
	int gpio_mode;
	int gpio_state;
	ext_irq_handler_t irq_handler;
};

struct pending_intr_list_info {
	u16 pending_intr_list[MAX_PENDING_INTR_LIST];
	int start_pos;
	int end_pos;
	int curr_num;
	spinlock_t spin_lock;
};

u16 ext_gpio_get_int_mask_reg(void);

/* for extern user start */
int ext_gpio_request(int gpio_no);
int ext_gpio_release(int gpio_no);

int ext_gpio_set_mode(int gpio_no, int mode, void *data);
int ext_gpio_get_mode(int gpio_no);

int ext_gpio_set_output_state(int gpio_no, int state);
int ext_gpio_get_state(int gpio_no);

int ext_irq_ack(int gpio_no);
/* for extern user end */

void ext_gpio_int_process(u16 value);

int ext_gpio_init(struct esp_pub *epub);
void ext_gpio_deinit(void);
#endif				/* _ESP_EXT_H_ */

#endif				/* USE_EXT_GPIO */
